/*
*	Project: Aethon
*
*	File: Director.cpp
*
*	Author: Caleb Reinking
*
*	Date: 2/27/2009
*
*   Purpose: The director is the actual run class that includes int main() and
*            communicates directly with the Scene and StageHand classes
*/

#include "../include/Director.h"
#include <GL/gl.h>
#include <GL/glut.h>
#include "../include/Control.h"
#include "../include/Control2.h"
#include "../include/Timer.h"
#include "../include/Eye.h"
#include "../include/vector3f.h"
#include "../include/Model.h"
#include "../include/ModelPart.h"
#include "../include/Eye.h"
#include "../include/Terrain.h"
#include <iostream>
#include <assert.h>
#include <string>

using namespace std;
	
// Constants
const unsigned int MAX_BUFFER_SIZE = 40;
const int WINDOW_WIDTH = 640;
const int WINDOW_HEIGHT = 480;
const int DISTANCE = 20;	

// Global Variables
int sizeOfTeapot = 6;
bool wireFrameDesired = false;
Model myModel;
Model box_1m;
Model camera;
Eye myeye;

//singleton declarations
Timer *allTheTimeWeNeed = Timer::getInstanceof();
Control *myControl = Control::getInstanceof();
Control2 *myControl2 = Control2::getInstanceof();
int handleNumber = 1;

Terrain testTerrain;
//int xRotateAmt = 0;
//int yRotateAmt = 0;
//int zRotateAmt = 0;
bool axisLinesDesired = true;

// Function Prototypes
void display(void);
void myReshape(int w, int h);
void createModel();
void update();//test director code, updates model velocity and direction, 
//will also call collision check for physmanager
void generateNewPosition(Model& modelA);//test for velocity based movement
void checkHandleNumber();
// Caleb's Function Protos
//void handleKeyboard( unsigned char key, int x, int y );
void drawAxisLines();
//void handleMotion( int x, int y );
//void mouseButton(int button, int state, int x, int y);

//-------------------------------------------------------------------------	
//------------------- Methods ---------------------------------------------
//##########################################################################
void Director::run()
{
   
}
	
//##########################################################################
int main( int argc, char* argv[] )
{
	
    glutInit(&argc, argv);
    
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT);
    glutCreateWindow("3D Teapot (Orthographic)");
    glutReshapeFunc(myReshape);
    glutDisplayFunc(display);
    glutSetCursor(GLUT_CURSOR_NONE);

    handleNumber = 1;//1 indicates control handler, 2 for stage hand
	glutPassiveMotionFunc(Control::mouseHandle);
    createModel();//create test model for control to adjust
    glutWarpPointer(320,240);//set pointer at center
    
    //#####################################
	//set control pointer values
	myControl->setHandleNumberPtr(&handleNumber);//point to
	myControl2->setHandleNumberPtr(&handleNumber);
	glutKeyboardFunc(Control::keyboardHandle);
	myControl->setIsActive(true);//indicates that control is the active handler
	myControl->setModelPtr(&camera);//set control pointer as camera
	myControl2->setIsActive(false);
    //#####################################
    glEnable(GL_DEPTH_TEST);
    glClearDepth(1.0);
    glEnable(GL_TEXTURE_2D); 
    glClearColor(0.5, 0.5, 0.5, 1.0); // Gray
    
    //Initialization MUST take place before using display lists! otherwise no
    //display lists can be generated
        
    //srand(time(0));
    testTerrain = Terrain();
	testTerrain.load( "heightmapTexture", "texture2flip" );
    //cout << "terrain created" << endl;
    myModel.load("tilion");
    myModel.setPosition(vector3f(10,10,10));
    myModel.setDirection(vector3f(0,225,0));
    box_1m.load("box_1m");
    box_1m.setPosition(vector3f(10,9,13));
    box_1m.toggleCollisionSphereVisibility();
    glutMainLoop();
    return 0;
        
}

// ######################################################################
void display(void)
{
glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

if (wireFrameDesired)
   glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
else
   glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);


update();
checkHandleNumber();

testTerrain.display();

box_1m.display();
myModel.display();
drawAxisLines();

glFlush();
glutSwapBuffers();
} // End display

void myReshape(int width, int height)
{
const int DISTANCE = 10000;
const int FOV_ANGLE = 45;

glViewport(0, 0, width, height);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();

gluPerspective(FOV_ANGLE,  (float) width / (float) height, 1.0, DISTANCE);

cout << "New window size: " << width << " x " << height << endl;
glMatrixMode(GL_MODELVIEW);
} // End myReshape

void createModel()
{
	vector3f pos(0,8.0,0);
	vector3f dir(0,0,0);
	vector3f vel(0,0,0);
	camera.setPosition(pos);
	camera.setDirection(dir);
	camera.setVelocity(vel);
	
	vector3f look(0,0,1);
	myeye.setLookAt(look);//set look to zeros
	myeye.setIsActive(true);
	myeye.update(pos,dir);
	
}//end function

void update()
{
myControl->updateVelocity();
myControl->updateDirection();
myeye.update(camera.getPosition(),camera.getDirection());
generateNewPosition(camera);
cout<<"We have some time: " << allTheTimeWeNeed->getTime()<<endl;
allTheTimeWeNeed->incrementTime();
checkHandleNumber();
}

void generateNewPosition(Model& modelA)
{//for now it just sets position, ignoring collisions so that we can move the camera
	vector3f tempVel = modelA.getVelocity();
	vector3f tempPos = modelA.getPosition();

	tempPos.v[0] += tempVel.v[0];
	tempPos.v[1] += tempVel.v[1];
	tempPos.v[2] += tempVel.v[2];
	
	modelA.setPosition(tempPos);
	vector3f zeroVect(0,0,0);
	modelA.setVelocity(zeroVect);
}//end gennewPosition
	
//####################################
void drawAxisLines()
{
     glBegin( GL_LINES );
        glLineWidth(3);
        glColor3ub( 255, 0, 0 );
        glVertex3f( 0.0, 0.0, 0.0 );
        glVertex3f( 100.0, 0.0, 0.0 );
        
        glColor3ub( 0, 255, 0 );
        glVertex3f( 0.0, 0.0, 0.0 );
        glVertex3f( 0.0, 100.0, 0.0 );
        
        glColor3ub( 0, 0, 255 );
        glVertex3f( 0.0, 0.0, 0.0 );
        glVertex3f( 0.0, 0.0, 100.0 );
        
        glLineWidth(1);
     glEnd();
}

//####################################
void checkHandleNumber()
{
	//checking to see which handler to register
	if(handleNumber==1)//should be control::handler active
	{
		if(myControl->getIsActive()==false)
		{
		glutKeyboardFunc(Control::keyboardHandle);
		myControl->setIsActive(true);
		}//end if
	}//end if handlerNumber==1
	
	else if(handleNumber==2)//should be stagehand::handler active
	{
		if(myControl2->getIsActive()==false)
		{
		glutKeyboardFunc(Control2::keyboardHandle);
		myControl2->setIsActive(true);
		}//end if
	}//end if handlerNumber==2

}//end checkHandlerNumber